/**
 * 
 */
package com.fox.webapp.persistent.impl;

import static org.springframework.data.mongodb.core.query.Criteria.where;

import java.util.regex.Pattern;

import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.FindAndModifyOptions;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.BasicQuery;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.util.StringUtils;

import com.fox.webapp.domain.Account;
import com.fox.webapp.domain.Person;
import com.fox.webapp.persistent.AccountRepository;
import com.fox.webapp.persistent.custom.AccountRepositoryCustom;

/**
 * @author yockii
 * 
 */
public class AccountRepositoryImpl implements AccountRepositoryCustom {

	@Autowired
	private MongoTemplate mt;

	@Override
	public Account updateAccountOnlySelfDesc(Account a) {
		Query query = new Query(where("id").is(a.getId()));
		Update update = new Update();
		if(StringUtils.hasText(a.getSelfDesc())){
			update.set("selfDesc", a.getSelfDesc());
		}
		if(a.getMinToPay() != null){
			update.set("minToPay", a.getMinToPay() > 1?a.getMinToPay():1.0);
		}
		return mt.findAndModify(query, update, FindAndModifyOptions.options()
				.returnNew(true), Account.class);
	}

	@Override
	public Account activeAccount(Account a) {
		Query query = new Query(where("id").is(a.getId()));
		Update update = new Update();
		update.set("active", a.getActive());

		return mt.findAndModify(query, update, FindAndModifyOptions.options()
				.returnNew(true), Account.class);
	}

	@Override
	public Account addCommission(Account account, Double commission) {
		Query query = new Query(where("id").is(account.getId()));
		Update update = new Update();
		update.inc("totalCommission", commission);
		return mt.findAndModify(query, update, FindAndModifyOptions.options()
				.returnNew(true), Account.class);
	}

	@Override
	public long countMine(Person p) {
		Query query = new Query(where("person").is(p));
		return mt.count(query, Account.class);
	}

	@Override
	public Page<Account> findAccountByCondition(Account account,
			Pageable pageRequest) {
		Query query = new Query();
		if(account.isLookingForPay()){
			query = new BasicQuery("{$where: \"this.totalCommission - this.totalPayed > this.minToPay\"}");
		}
		if(StringUtils.hasText(account.getAccountNo())){
			query.addCriteria(where("accountNo").is(account.getAccountNo()));
		}
		if(StringUtils.hasText(account.getBrokerName())){
			query.addCriteria(where("brokerName").is(account.getBrokerName()));
		}
		if(account.getPerson() != null && account.getPerson().getId() != null){
			query.addCriteria(where("person").is(account.getPerson()));
		}
		long total = mt.count(query, Account.class);
		query.skip(pageRequest.getOffset());
		query.limit(pageRequest.getPageSize());
		return new PageImpl<Account>(mt.find(query, Account.class), pageRequest, total);
	}

	@Override
	public Account recordAccountCommission(String accountNo, String brokerName,
			double commission) {
		Query query = new Query();
		if(!StringUtils.hasText(accountNo) || !StringUtils.hasText(brokerName)){
			return null;
		}
		query.addCriteria(where("accountNo").is(accountNo)).addCriteria(where("brokerName").regex(Pattern.compile(brokerName, Pattern.CASE_INSENSITIVE)));
		Update update = new Update();
		update.set("lastPay", commission);
		update.inc("totalPayed", commission);
		return mt.findAndModify(query, update, FindAndModifyOptions.options()
				.returnNew(true), Account.class);
	}

	@Override
	public Account recordAccountCommission(Account account) {
		Query query = new Query(where("id").is(account.getId()));
		double d = account.getTotalCommission() - account.getTotalPayed();
		Update update = new Update().set("lastPay", d).inc("totalPayed", d);
		return mt.findAndModify(query, update, FindAndModifyOptions.options().returnNew(true), Account.class);
	}

}
